package com.qike.duola.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.qike.duola.domain.*;
import com.qike.duola.dto.UserAddDto;
import com.qike.duola.dto.UserDelDto;
import com.qike.duola.dto.UserEditDto;
import com.qike.duola.dto.UserListDto;
import com.qike.duola.enums.StatusEnums;
import com.qike.duola.mapper.*;
import com.qike.duola.service.DuolaMessageService;
import com.qike.duola.service.IsysRoleService;
import com.qike.duola.service.IsysUserService;
import com.qike.duola.shiro.jwt.JwtToken;
import com.qike.duola.utils.FileUtil;
import com.qike.duola.utils.MD5Util;
import com.qike.duola.utils.TimeTool;
import com.qike.duola.utils.TokenUtil;
import com.qike.duola.vo.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.mobile.device.Device;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Author: Eric.zhou
 * @Date: 2020/7/31 10:30
 */
@Service
public class SysUserServiceImpl implements IsysUserService {
    private static final Logger logger = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private DuolaDeptMapper duolaDeptMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private IsysRoleService roleService;

    @Autowired
    private DuolaTrainMapper duolaTrainMapper;
    @Autowired
    private DuolaTrainUserMapper duolaTrainUserMapper;
    @Autowired
    private TokenUtil tokenUtil;



    @Override
    public LoginVo login(String userName, String pwd, Device device, HttpServletRequest request, HttpServletResponse response) throws Exception {

        SysUserWithBLOBs sysUser = sysUserMapper.selectByAccount(userName);
        if (sysUser==null){
            throw new Exception("账户不存在");
        }
        if (sysUser.getStatus()==0) {
            throw new Exception("账号已被禁用,请联系管理员!");
        }
        String password = sysUser.getPassword();
        String passwordMd5Str = MD5Util.string2MD5(pwd);
        if (!passwordMd5Str.equals(sysUser.getPassword())){
            throw new Exception("密码错误");
        }
        // 验证用户名密码成功后生成token
        String token = tokenUtil.generateToken(sysUser.getId().toString(), device);
        // 构建JwtToken
//        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, password);
        JwtToken jwtToken = JwtToken.builder().token(token).principal(userName).build();
        Subject subject = SecurityUtils.getSubject();
        try {
            // 该方法会调用JwtRealm中的doGetAuthenticationInfo方法
            subject.login(jwtToken);
        } catch (UnknownAccountException exception) {
            exception.printStackTrace();
            System.out.println("账号不存在");
        } catch (IncorrectCredentialsException exception) {
            exception.printStackTrace();
            System.out.println("错误的凭证，用户名或密码不正确");
        } catch (LockedAccountException exception) {
            exception.printStackTrace();
            System.out.println("账户已锁定");
        } catch (ExcessiveAttemptsException exception) {
            exception.printStackTrace();
            System.out.println("错误次数过多");
        } catch (AuthenticationException exception) {
            exception.printStackTrace();
            System.out.println("认证失败");
        }

        // 认证通过
        if(subject.isAuthenticated()){
            // 将token写出到cookie
            Cookie cookie =new Cookie("token",token);
            cookie.setHttpOnly(true);
            cookie.setMaxAge(3600 * 5);
            cookie.setPath("/");
            response.addCookie(cookie);
            response.flushBuffer();
            LoginVo loginVo = new LoginVo();
            loginVo.setUserName(sysUser.getUserName());
            String nick = new String(sysUser.getNickname());
            loginVo.setNiName(sysUser.getNickname());
//            loginVo.setNiName("和接口大会上就看我");
            loginVo.setUid(sysUser.getId());
            loginVo.setToken(token);
            return loginVo;
        }else {
            throw new Exception("登录失败");
        }
    }

    /**
     * 添加人员
     *
     * @param userAddDto
     */
    @Override
    @Transactional
    public void userAdd(UserAddDto userAddDto) throws Exception {
        Long userId = (Long) SecurityUtils.getSubject().getPrincipal();
        logger.info(userId+"添加人员"+ JSON.toJSON(userAddDto));
        SysUserWithBLOBs sysUserWithBLOBs = sysUserMapper.selectByAccount(userAddDto.getPhone());
        if (sysUserWithBLOBs!=null){
            throw new Exception("用户已经创建");
        }
        SysUserWithBLOBs user = new SysUserWithBLOBs();
        user.setCreateBy(userId);
        user.setPassword("e10adc3949ba59abbe56e057f20f883e");
        user.setStatus(StatusEnums.NO.getEcode());
        user.setUserName(userAddDto.getPhone());
        user.setCreateAt(LocalDateTime.now());
        user.setNickname(userAddDto.getName());
        user.setSex(userAddDto.getSex());
        user.setAddress(userAddDto.getAddress());
        user.setAge(userAddDto.getAge());
        user.setPlatId(1);
        user.setMobilePhone(userAddDto.getPhone());
        user.setUrgentName(userAddDto.getUrgentName());
        user.setUrgentPhone(userAddDto.getUrgentPhone());
        user.setBankNo(userAddDto.getBanNo());
        user.setDeptId(userAddDto.getDeptId());
        user.setEmployee(userAddDto.getEmployee());
        //用户角色
        user.setIsOnTry(userAddDto.getIsOnTry());
        user.setIsLeave(userAddDto.getIsLeave());
        user.setIdCardFront(userAddDto.getIdCardFront());
        user.setIdCardBack(userAddDto.getIdCardBack());
        user.setCertificate(userAddDto.getCertificate());
        user.setResume(userAddDto.getResume());
        if (userAddDto.getJoinTime()!=null){
            user.setJoinTime(TimeTool.LongToLocalDateTime(Long.valueOf(userAddDto.getJoinTime())));
        }
        if (!StringUtils.isEmpty(userAddDto.getOutTime())){
            user.setOuttime(TimeTool.LongToLocalDateTime(Long.valueOf(userAddDto.getOutTime())));
            user.setOutReason(userAddDto.getOutReason());
        }
        if (userAddDto.getTryTimeStart()!=null){
            user.setTryTimeStart(TimeTool.LongToLocalDateTime(Long.valueOf(userAddDto.getTryTimeStart())));
            user.setTryTimeEnd(TimeTool.LongToLocalDateTime(Long.valueOf(userAddDto.getTryTimeEnd())));
        }
        sysUserMapper.insertSelective(user);
        //用户角色绑定
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(user.getId());
        sysUserRole.setRoleId(userAddDto.getRoleId());
        sysUserRoleMapper.insertSelective(sysUserRole);
    }

    /**
     * 编辑员工
     *
     * @param userEditDto
     */
    @Override
    public void userEdit(UserEditDto userEditDto) throws Exception {
        Long userId = (Long) SecurityUtils.getSubject().getPrincipal();
        logger.info(userId+"编辑员工"+ JSON.toJSON(userEditDto));
        SysUserWithBLOBs sysUserWithBLOBs = sysUserMapper.selectByAccount(userEditDto.getPhone());
        if (sysUserWithBLOBs==null){
            throw new Exception("数据异常");
        }
        SysUserWithBLOBs user = new SysUserWithBLOBs();
        user.setId(sysUserWithBLOBs.getId());
        user.setUpdateBy(userId);
        user.setStatus(StatusEnums.NO.getEcode());
        user.setUserName(userEditDto.getPhone());
        user.setUpdateAt(LocalDateTime.now());
        user.setNickname(userEditDto.getName());
        user.setSex(userEditDto.getSex());
        user.setAddress(userEditDto.getAddress());
        user.setAge(userEditDto.getAge());
        user.setMobilePhone(userEditDto.getPhone());
        user.setUrgentName(userEditDto.getUrgentName());
        user.setUrgentPhone(userEditDto.getUrgentPhone());
        user.setBankNo(userEditDto.getBanNo());
        user.setDeptId(userEditDto.getDeptId());
        user.setEmployee(userEditDto.getEmployee());
        if (!StringUtils.isEmpty(userEditDto.getTryTimeStart())){
            user.setTryTimeStart(TimeTool.LongToLocalDateTime(userEditDto.getTryTimeStart()));
            user.setTryTimeEnd(TimeTool.LongToLocalDateTime(userEditDto.getTryTimeEnd()));
        }
        if (!StringUtils.isEmpty(userEditDto.getJoinTime())){
            user.setJoinTime(TimeTool.LongToLocalDateTime(Long.valueOf(userEditDto.getJoinTime())));
        }
        if (!StringUtils.isEmpty(userEditDto.getOutTime())){
            user.setOuttime(TimeTool.LongToLocalDateTime(Long.valueOf(userEditDto.getJoinTime())));
            user.setOutReason(userEditDto.getOutReason());
        }
        //用户角色
        user.setIsOnTry(userEditDto.getIsOnTry());
        user.setIsLeave(userEditDto.getIsLeave());
        user.setIdCardFront(userEditDto.getIdCardFront());
        user.setIdCardBack(userEditDto.getIdCardBack());
        user.setCertificate(userEditDto.getCertificate());
        user.setResume(userEditDto.getResume());
        sysUserMapper.updateByPrimaryKeySelective(user);
        //用户角色绑定
        SysUserRoleExample example = new SysUserRoleExample();
        SysUserRole sysUserRole = new SysUserRole();

        example.createCriteria().andUserIdEqualTo(userEditDto.getId());
        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectByExample(example);
        if (sysUserRoles.size()>0){
            sysUserRole = sysUserRoles.get(0);
            sysUserRole.setUserId(user.getId());
            sysUserRole.setRoleId(userEditDto.getRoleId());
            sysUserRoleMapper.updateByPrimaryKey(sysUserRole);
        }else {
            sysUserRole.setUserId(user.getId());
            sysUserRole.setRoleId(userEditDto.getRoleId());
            sysUserRoleMapper.insertSelective(sysUserRole);
        }

    }

    /**
     * 删除员工
     *
     * @param userDelDto
     */
    @Override
    public void userDel(UserDelDto userDelDto) throws Exception {
        Long userId = (Long) SecurityUtils.getSubject().getPrincipal();
        logger.info(userId+"删除员工"+ JSON.toJSON(userDelDto));
        SysUserWithBLOBs sysUserWithBLOBs = sysUserMapper.selectByPrimaryKey(userDelDto.getId());
        if (sysUserWithBLOBs==null  ){
            throw new Exception("数据异常");
        }
        sysUserWithBLOBs.setStatus(StatusEnums.YES.getEcode());
        sysUserMapper.updateByPrimaryKey(sysUserWithBLOBs);
    }

    /**
     * 员工列表
     *
     * @param userListDto
     * @return
     */
    @Override
    public UserListVo userList(UserListDto userListDto) {
        Long userId = (Long) SecurityUtils.getSubject().getPrincipal();
        logger.info(userId+"员工列表"+ JSON.toJSON(userListDto));
        UserListVo userListVo = new UserListVo();
        List<UserVo> list = new ArrayList<>();
        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo(StatusEnums.NO.getEcode()).andPlatIdEqualTo(1);
        if (!StringUtils.isEmpty(userListDto.getName())){
            criteria.andNicknameLike(userListDto.getName());
        }
        if (!StringUtils.isEmpty(userListDto.getPhone())){
            criteria.andMobilePhoneEqualTo(userListDto.getPhone());
        }
        if (userListDto.getDeptId()!=null){
            criteria.andDeptIdEqualTo(userListDto.getDeptId());
        }
        if (userListDto.getIsLeave()!=null){
            criteria.andIsLeaveEqualTo(userListDto.getIsLeave());
        }
        Map<Integer,String> deptName = new HashMap<>();
        DuolaDeptExample deptExample = new DuolaDeptExample();
        deptExample.createCriteria().andStatusEqualTo(StatusEnums.NO.getEcode());
        List<DuolaDept> duolaDepts = duolaDeptMapper.selectByExample(deptExample);
        for (DuolaDept duolaDept : duolaDepts) {
            deptName.put(duolaDept.getId(),duolaDept.getDeptName());
        }
        example.setOrderByClause("create_at desc");
        Page page = PageHelper.startPage(userListDto.getStartPage(), userListDto.getPageSize());
        List<SysUserWithBLOBs> sysUserWithBLOBs = sysUserMapper.selectByExampleWithBLOBs(example);
        for (SysUserWithBLOBs sysUserWithBLOB : sysUserWithBLOBs) {
            UserVo vo = new UserVo();
            vo.setName(sysUserWithBLOB.getNickname());
            vo.setEmployee(sysUserWithBLOB.getEmployee());
            vo.setId(sysUserWithBLOB.getId());
            //查询部门名称
            if (sysUserWithBLOB.getDeptId()!=null){
                vo.setDeptName(deptName.get(sysUserWithBLOB.getDeptId()));
            }
            vo.setJoinTime(TimeTool.LocalDateTimeFormatNoTime(sysUserWithBLOB.getJoinTime()));
            vo.setIsLeave(sysUserWithBLOB.getIsLeave());
            if (sysUserWithBLOB.getOuttime()==null){
                vo.setOutTime(null);
            }else {
                vo.setOutTime(TimeTool.LocalDateTimeFormatNoTime(sysUserWithBLOB.getOuttime()));
            }

            vo.setEmployee(sysUserWithBLOB.getEmployee());
            vo.setPhone(sysUserWithBLOB.getMobilePhone());
            list.add(vo );
        }
        userListVo.setList(list);
        userListVo.setTotal(page.getTotal());


        return userListVo;
    }

    /**
     * 用户详情
     *
     * @param id
     * @return
     */
    @Override
    public UserInfoVo userInfo(Long id) throws Exception {
        Long userId = (Long) SecurityUtils.getSubject().getPrincipal();
        logger.info(userId+"用户详情"+ JSON.toJSON(id));
        SysUserWithBLOBs sysUserWithBLOBs = sysUserMapper.selectByPrimaryKey(id);
        if (sysUserWithBLOBs==null){
            throw new Exception("数据异常");
        }
        UserInfoVo vo = new UserInfoVo();
        vo.setOutReason(sysUserWithBLOBs.getOutReason());
        vo.setPhone(sysUserWithBLOBs.getMobilePhone());
        vo.setName(sysUserWithBLOBs.getNickname());
        vo.setSex(sysUserWithBLOBs.getSex());
        vo.setAddress(sysUserWithBLOBs.getAddress());
        vo.setAge(sysUserWithBLOBs.getAge());
        vo.setUrgentName(sysUserWithBLOBs.getUrgentName());
        vo.setUrgentPhone(sysUserWithBLOBs.getUrgentPhone());
        vo.setBanNo(sysUserWithBLOBs.getBankNo());
        vo.setDeptId(sysUserWithBLOBs.getDeptId());
        vo.setEmployee(sysUserWithBLOBs.getEmployee());
        vo.setIsOnTry(sysUserWithBLOBs.getIsOnTry());
        vo.setTryTimeStart(TimeTool.LocalDateTimeFormatNoTime(sysUserWithBLOBs.getTryTimeStart()));
        vo.setTryTimeEnd(TimeTool.LocalDateTimeFormatNoTime(sysUserWithBLOBs.getTryTimeEnd()));
        //用户角色
        List<SysRole> roleByUid = roleService.getRoleByUid(id);
        if (roleByUid!=null){
            SysRole sysRole = roleByUid.get(0);
            vo.setRoleId(sysRole.getId());
            vo.setRoleName(sysRole.getName());
        }
        vo.setIsOnTry(sysUserWithBLOBs.getIsOnTry());
        vo.setIsLeave(sysUserWithBLOBs.getIsLeave());
        vo.setOutTime(TimeTool.LocalDateTimeFormatNoTime(sysUserWithBLOBs.getOuttime()));
        vo.setJoinTime(TimeTool.LocalDateTimeFormatNoTime(sysUserWithBLOBs.getJoinTime()));
        vo.setIdCardFront(sysUserWithBLOBs.getIdCardFront());
        vo.setIdCardBack(sysUserWithBLOBs.getIdCardBack());
        vo.setCertificate(sysUserWithBLOBs.getCertificate());
        vo.setResume(sysUserWithBLOBs.getResume());
        vo.setCertificateName(FileUtil.getFileName(sysUserWithBLOBs.getCertificate()));
        //获取所有培训
        DuolaTrainExample trainExample = new DuolaTrainExample();
        trainExample.createCriteria().andStatusEqualTo(StatusEnums.NO.getEcode());
        List<DuolaTrain> duolaTrains = duolaTrainMapper.selectByExample(trainExample);
        Map<Integer,DuolaTrain> trainMap = new HashMap<>();
        for (DuolaTrain duolaTrain : duolaTrains) {
            trainMap.put(duolaTrain.getId(),duolaTrain);
        }
        DuolaTrainUserExample trainUserExample = new DuolaTrainUserExample();
        trainUserExample.createCriteria().andUidEqualTo(id).andStatusEqualTo(StatusEnums.NO.getEcode());
        List<DuolaTrainUser> duolaTrainUsers = duolaTrainUserMapper.selectByExample(trainUserExample);
        List<UserTrainList> trainList = new ArrayList<>();
        for (DuolaTrainUser duolaTrainUser : duolaTrainUsers) {
            UserTrainList userTrainList = new UserTrainList();
            userTrainList.setId(duolaTrainUser.getId());
            userTrainList.setScore(duolaTrainUser.getScore());

            userTrainList.setTrainTime( TimeTool.LocalDateTimeFormatNoTime(trainMap.get(duolaTrainUser.getTrainId()).getStartTime()));
            userTrainList.setTrainName(trainMap.get(duolaTrainUser.getTrainId()).getTitle());
            trainList.add(userTrainList);
        }
        vo.setTrainList(trainList);
        return vo;
    }

    /**
     * 人员下拉列表
     *
     * @param name
     * @return
     */
    @Override
    public List<UserPullListVo> userPullList(String name) {
        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo(StatusEnums.NO.getEcode());
        criteria.andIsLeaveEqualTo(StatusEnums.YES.getEcode());
        if (!StringUtils.isEmpty(name)){
            criteria.andNicknameLike(name);
        }
        List<UserPullListVo> list = new ArrayList<>();

        List<SysUser> sysUsers = sysUserMapper.selectByExample(example);
        for (SysUser sysUser : sysUsers) {
            UserPullListVo vo = new UserPullListVo();
            vo.setUid(sysUser.getId());
            vo.setName(sysUser.getNickname());
            list.add(vo);
        }
        return list;
    }

    /**
     * 通过id获取人员 不传id 就是空
     *
     * @param id
     * @return
     */
    @Override
    @Cacheable(value="getAllUser", key="#id")
    public List<SysUser> getAllUser(Long id) {
        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria();
        if (id!=null){
            criteria.andIdEqualTo(id);
        }
        List<SysUser> sysUsers = sysUserMapper.selectByExample(example);
        return sysUsers;
    }

    /**
     * 根据部门,姓名查询人员下拉列表
     *
     * @param deptId
     * @param name
     * @return
     */
    @Override
    public List<UserPullListVo> userPullListByDeptId(Integer deptId, String name) {
        //部门
        DuolaDeptExample duolaDeptExample = new DuolaDeptExample();
        DuolaDeptExample.Criteria criteria1 = duolaDeptExample.createCriteria();
        if (deptId!=null){
            criteria1.andIdEqualTo(deptId);
        }

        List<DuolaDept> duolaDepts = duolaDeptMapper.selectByExample(duolaDeptExample);
        Map<Integer,String> deptMap = new HashMap<>();
        for (DuolaDept duolaDept : duolaDepts) {
            deptMap.put(duolaDept.getId(),duolaDept.getDeptName());
        }

        SysUserExample example = new SysUserExample();
        SysUserExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo(StatusEnums.NO.getEcode());
        criteria.andIsLeaveEqualTo(StatusEnums.YES.getEcode());
        if (!StringUtils.isEmpty(name)){
            criteria.andNicknameLike(name);
        }
        List<UserPullListVo> list = new ArrayList<>();

        List<SysUser> sysUsers = sysUserMapper.selectByExample(example);
        for (SysUser sysUser : sysUsers) {
            UserPullListVo vo = new UserPullListVo();
            vo.setUid(sysUser.getId());
            vo.setName(sysUser.getNickname());
            if (!StringUtils.isEmpty(deptMap.get(sysUser.getDeptId()))){
                vo.setDept(deptMap.get(sysUser.getDeptId()));
                list.add(vo);
            }
        }
        return list;
    }

    /**
     * 获取用户详情
     *
     * @return
     */
    @Override
    public GetUserInfoVo getUserInfo() {
        Long userId = (Long) SecurityUtils.getSubject().getPrincipal();
        SysUserWithBLOBs sysUserWithBLOBs = sysUserMapper.selectByPrimaryKey(userId);
        GetUserInfoVo vo = new GetUserInfoVo();
        vo.setUid(sysUserWithBLOBs.getId());
        vo.setPhoto(sysUserWithBLOBs.getAvatar());
        vo.setName(sysUserWithBLOBs.getNickname());
        return vo;
    }
}
